package cn.taketoday.live.controller;

import com.alibaba.fastjson.JSONObject;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.taketoday.live.Json;
import cn.taketoday.live.config.CenterSetConfig;
import cn.taketoday.live.config.GlobalData;
import cn.taketoday.live.data.LoginData;
import cn.taketoday.live.data.Qrcode;
import cn.taketoday.live.data.room.RoomBlock;
import cn.taketoday.live.http.BilibiliHttpRequests;
import cn.taketoday.live.http.HttpOtherData;
import cn.taketoday.live.http.HttpRoomData;
import cn.taketoday.live.service.ClientService;
import cn.taketoday.live.service.SettingsService;
import cn.taketoday.live.utils.FileUtils;
import cn.taketoday.live.utils.ObjectUtils;
import cn.taketoday.live.utils.QrcodeUtils;

/**
 * @author Jane
 * @ClassName ApiController
 * @Description TODO
 * @date 2021/4/12 16:04
 * @Copyright:2021
 */
@RestController
@RequestMapping("/api")
public class ApiController {

  private SettingsService checkService;

  private ClientService clientService;

  /**
   * @api {GET} /api/index index
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 获取主页信息-index
   * @apiDescription 获取主页信息
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"xnwAnYbTa","result":{},"code":"WjXiGeCHP"}
   */
  @GetMapping("/index")
  public Json index() {
    IndexData dataParam = new IndexData();
    dataParam.setEdition(GlobalData.EDITION);
    dataParam.setAnchorName(GlobalData.ANCHOR_NAME);
    dataParam.setManager(GlobalData.USERMANAGER != null && GlobalData.USERMANAGER.isIs_manager());
    dataParam.setPopularity(GlobalData.ROOM_POPULARITY);
    dataParam.setRoomId(GlobalData.ROOM_ID);
    dataParam.setUser(GlobalData.USER);
    return Json.ok(dataParam);
  }

  /**
   * @api {GET} /api/connect connect
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 获取历史连接房间-connect
   * @apiDescription 获取历史连接房间
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"liHlP6","result":{},"code":"zbg5udzW0"}
   */
  @GetMapping("/connect")
  public Json connect() {
    return Json.ok(GlobalData.centerSetConf.getRoomid());
  }

  /**
   * @api {GET} /api/quit quit
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 退出登录-quit
   * @apiDescription 退出登录
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"EoS0dG5Z","result":{},"code":"y3D"}
   */
  @GetMapping("/quit")
  public Json quit() {
    if (!StringUtils.isEmpty(GlobalData.USERCOOKIE)) {
      BilibiliHttpRequests.quit();
      checkService.quit();
      Json.ok(0);
    }
    return Json.ok(1);
  }

  /**
   * @api {GET} /api/qrcode qrcode
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 获取二维码图片-qrcode
   * @apiDescription 获取二维码图片接口
   * @apiParam (请求参数) {String} url
   * @apiParamExample 请求参数示例
   * url=t0
   * @apiSuccess (响应结果) {Object} response
   * @apiSuccessExample 响应结果示例
   * null
   */
  @RequestMapping(value = "/qrcode", method = RequestMethod.GET)
  public void qrcode(HttpServletResponse resp, @RequestParam("url") String url) throws Exception {
    QrcodeUtils.creatRrCode(url, 140, 140, resp);
  }

  /**
   * @api {POST} /api/qrcodeUrl qrcodeUrl
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 获取二维码图片链接包括key-qrcodeUrl
   * @apiDescription 获取二维码图片链接包括key key需要扫码最后一部传给后台
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"EQt1ZLezYX","result":{},"code":"u"}
   */
  @PostMapping("/qrcodeUrl")
  public Json qrcodeUrl() {
    Qrcode qrcode = BilibiliHttpRequests.getQrcode();
    LoginData loginData = new LoginData();
    loginData.setOauthKey(qrcode.getOauthKey());
    loginData.setGourl(qrcode.getUrl());
//        req.getSession().setAttribute("auth", qrcode.getOauthKey());
    return Json.ok(loginData);
  }

  /**
   * @api {POST} /api/loginCheck loginCheck
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 轮询扫码状态-loginCheck
   * @apiDescription 轮询扫码状态
   * @apiParam (请求参数) {String} oauthKey 二维码图片接口获取的key
   * @apiParamExample 请求参数示例
   * oauthKey=x63hUCoxIN
   * @apiSuccess (响应结果) {Object} response
   * @apiSuccessExample 响应结果示例
   * {}
   */
  @RequestMapping(value = "/loginCheck", method = RequestMethod.POST)
  public JSONObject loginCheck(HttpServletRequest req, @RequestParam("oauthKey") String oauthKey) {
//        if (req.getSession().getAttribute("status") != null)
//            return null;
    JSONObject jsonObject = null;
    LoginData loginData = new LoginData();
    loginData.setOauthKey(oauthKey);
    String jsonString = BilibiliHttpRequests.getCookie(loginData);
    jsonObject = JSONObject.parseObject(jsonString);
    if (jsonObject != null) {
      if (jsonObject.getBoolean("status")) {
        checkService.init(1);
//                if (PublicDataConf.USER != null) {
//                    req.getSession().setAttribute("status", "login");
//                }
      }
    }
    return jsonObject;
  }

  /**
   * @api {GET} /api/loginCheck loginCheck
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 登录状态检查接口-loginCheck
   * @apiDescription 登录状态检查接口
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"K1","result":{},"code":"b"}
   */
  @GetMapping("/loginCheck")
  public Json loginCheck(HttpServletRequest req) {
    BilibiliHttpRequests.getUserInfo();
    if (StringUtils.isNotBlank(GlobalData.USERCOOKIE)) {
      return Json.ok(0);
    }
    return Json.ok(1);
  }

  /**
   * @api {GET} /api/connectRoom connectRoom
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 连接房间-connectRoom
   * @apiDescription 连接房间
   * @apiParam (请求参数) {Number} roomid 要连接的房间号
   * @apiParamExample 请求参数示例
   * roomid=5980
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"1QrGH","result":{},"code":"VvATLV"}
   */
  @GetMapping("/connectRoom")
  public Json connectRoom(HttpServletRequest req, @RequestParam("roomid") Long roomid) throws Exception {
    boolean flag = false;
    if (null == GlobalData.webSocketProxy || !GlobalData.webSocketProxy.isOpen()) {
      clientService.startConnService(roomid);
      if (GlobalData.ROOM_ID != null) {
        GlobalData.centerSetConf.setRoomid(GlobalData.ROOM_ID);
        GlobalData.ROOMID_SAFE = GlobalData.ROOM_ID;
      }
      checkService.connectSet(GlobalData.centerSetConf);
    }
    if (GlobalData.webSocketProxy != null) {
      if (GlobalData.webSocketProxy.isOpen()) {
        flag = true;
      }
    }
    return Json.ok(flag);
  }

  /**
   * @api {GET} /api/disconnectRoom disconnectRoom
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 断开连接房间-disconnectRoom
   * @apiDescription 断开连接房间
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"IV8O","result":{},"code":"vyKwr"}
   */
  @RequestMapping(value = "/disconnectRoom", method = RequestMethod.GET)
  public Json disconnectRoom(HttpServletRequest req) {
    boolean flag = false;
    flag = clientService.closeConnService();
    return Json.ok(flag);
  }

  /**
   * @api {GET} /api/connectCheck connectCheck
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 连接检查-connectCheck
   * @apiDescription 连接检查
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"wfIIn","result":{},"code":"UVBxP"}
   */
  @RequestMapping(value = "/connectCheck", method = RequestMethod.GET)
  public Json connectCheck(HttpServletRequest req) {
    boolean flag = false;
    if (GlobalData.webSocketProxy != null) {
      if (GlobalData.webSocketProxy.isOpen()) {
        flag = true;
      }
    }
    return Json.ok(flag);
  }

  /**
   * @api {GET} /api/heartBeat heartBeat
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 心跳返回人气-heartBeat
   * @apiDescription 心跳返回人气（建议30秒更新一次）
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"lz5B","result":{},"code":"372r"}
   */
  @RequestMapping(value = "/heartBeat", method = RequestMethod.GET)
  public Json heartBeat(HttpServletRequest req) {
    return Json.ok(GlobalData.ROOM_POPULARITY);
  }

  /**
   * @api {GET} /api/getSet getSet
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 获取设置-getSet
   * @apiDescription 获取设置
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"T","result":{},"code":"H"}
   */
  @RequestMapping(value = "/getSet", method = RequestMethod.GET)
  public Json getSet(HttpServletRequest req) {
    return Json.ok(GlobalData.centerSetConf);
  }

  /**
   * @api {POST} /api/sendSet sendSet
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 保存设置-sendSet
   * @apiDescription 保存设置
   * @apiParam (请求参数) {String} set的json串
   * @apiParamExample 请求参数示例
   * set=VMNpNzrR
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"LyxCS","result":{},"code":"CCg"}
   */
  @PutMapping("/settings")
  public Json configure(@RequestBody CenterSetConfig config) {
    checkService.update(config);
    return Json.ok();
  }

  /**
   * @api {GET} /api/getIp getIp
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 获取ip地址-getIp
   * @apiDescription 获取ip地址
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"KcihQ","result":{},"code":"j9cMT"}
   */
  @GetMapping("/getIp")
  public Json getIp() {
    String ip = HttpOtherData.httpGetIp();
    if (!StringUtils.isEmpty(ip)) {
      return Json.ok((Object) ip);
    }
    return Json.ok();
  }

  /**
   * @api {GET} /api/checkupdate checkUpdate
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 检查更新-checkUpdate
   * @apiDescription 检查更新
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"7Zry","result":{},"code":"miC6Z8"}
   */
  @GetMapping("/checkupdate")
  public Json checkUpdate() {
    return Json.ok(1);
  }

  /**
   * @api {GET} /api/block block
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 禁言-block
   * @apiDescription 禁言
   * @apiParam (请求参数) {Number} uid 用户uid
   * @apiParam (请求参数) {Number} time 时间（1-720）
   * @apiParamExample 请求参数示例
   * uid=2800&time=175
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"tUInIsESzI","result":{},"code":"Le3H"}
   */
  @RequestMapping(value = "/block", method = RequestMethod.GET)
  public Json block(@RequestParam("uid") long uid, @RequestParam("time") short time) {
    short code = -1;
    if (time > 720 && time <= 0) {
      //required time error
      code = 2;
      return Json.ok(code);
    }
    if (StringUtils.isNotBlank(GlobalData.USERCOOKIE)) {
      code = BilibiliHttpRequests.addBlock(uid, time);
    }
    return Json.ok(code);
  }

  /**
   * @api {GET} /api/del_block del_block
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 撤销禁言-del_block
   * @apiDescription 撤销禁言
   * @apiParam (请求参数) {Number} id 禁言编号
   * @apiParamExample 请求参数示例
   * id=1423
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"dKI1M6","result":{},"code":"EmtOdc"}
   */
  @RequestMapping(value = "/del_block", method = RequestMethod.GET)
  public Json del_block(@RequestParam("id") long id) {
    short code = -1;
    code = BilibiliHttpRequests.deleteBlock(id);
    return Json.ok(code);
  }

  /**
   * @api {GET} /api/blocks blocks
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 分页获取封禁列表-blocks
   * @apiDescription 分页获取封禁列表
   * @apiParam (请求参数) {Number} page 页码
   * @apiParamExample 请求参数示例
   * page=5095
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"1piR","result":{},"code":"SeE5vB3"}
   */
  @RequestMapping(value = "/blocks", method = RequestMethod.GET)
  public Json blocks(@RequestParam("page") int page) {
    if (page <= 0) {
      page = 1;
    }
    List<RoomBlock> roomBlockList = new ArrayList<>();
    if (GlobalData.ROOM_ID != null && StringUtils
            .isNotBlank(GlobalData.USERCOOKIE) && GlobalData.USERMANAGER != null && GlobalData.USERMANAGER.isIs_manager()) {
      roomBlockList = HttpRoomData.getBlockList(page);
    }
    return Json.ok(roomBlockList);
  }

  /**
   * @api {GET} /api/setExport setExport
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 导出json配置文件-setExport
   * @apiDescription 导出json配置文件
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"Z8bzHv4","result":{},"code":"9yjaltwsf"}
   */
  @RequestMapping(value = "/setExport", method = RequestMethod.GET)
  public Json setExport() throws IOException {
    boolean flag = FileUtils.createJsonFile(GlobalData.centerSetConf.toJson());
    if (flag) {
      return Json.ok(0);
    }
    else {
      return Json.ok(1);
    }
  }

  /**
   * @api {POST} /api/setImport setImport
   * @apiVersion 1.0.0
   * @apiGroup ApiController
   * @apiName 导入设置-setImport
   * @apiDescription 导入设置(json文件)
   * @apiParam (请求参数) {Object} file 要上传json文件
   * @apiParamExample 请求参数示例
   * file=null
   * @apiSuccess (响应结果) {String} code
   * @apiSuccess (响应结果) {String} msg
   * @apiSuccess (响应结果) {Object} result
   * @apiSuccess (响应结果) {Number} timestamp
   * @apiSuccessExample 响应结果示例
   * {"msg":"JFPOd0","result":{},"code":"RKrqnj8x"}
   */
  @RequestMapping(value = "/setImport", method = RequestMethod.POST)
  public Json setImport(@RequestParam("file") MultipartFile file) throws IOException {
    if (!file.getResource().getFilename().endsWith(".json")) {
      return Json.ok(2);
    }
    String jsonString = new BufferedReader(new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8))
            .lines()
            .collect(Collectors.joining(System.lineSeparator()));
    try {
      final CenterSetConfig centerSetConfig = ObjectUtils.fromJSON(jsonString, CenterSetConfig.class);
      if (centerSetConfig != null) {
        GlobalData.centerSetConf = centerSetConfig;
        checkService.update(centerSetConfig);
      }
    }
    catch (Exception e) {
      return Json.ok(1);
    }
    return Json.ok(0);
  }

  @Autowired
  public void setCheckService(SettingsService checkService) {
    this.checkService = checkService;
  }

  @Autowired
  public void setClientService(ClientService clientService) {
    this.clientService = clientService;
  }
}
